<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Babylon + Oimo 双绳滑轮</title>
    <script src="https://cdn.babylonjs.com/babylon.js"></script>
    <script src="https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
    <script src="https://lo-th.github.io/Oimo.js/build/oimo.min.js"></script>
</head>
<body style="margin:0;overflow:hidden;">
<canvas id="renderCanvas"></canvas>

<script>
const canvas = document.getElementById("renderCanvas");
const engine = new BABYLON.Engine(canvas, true);
const scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color4(0.9,0.9,0.95,1);
const camera = new BABYLON.ArcRotateCamera("camera", Math.PI/4, Math.PI/3, 10, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0,1,0), scene);

// 物理世界
let world = new OIMO.World({ timestep: 1/60, gravity: [0, -9.8, 0], iterations: 8 });

// 固定点（四个角）
let anchorA = world.add({ type:"sphere", size:[0.1], pos:[-2, 3, 0], move:false });
let anchorB = world.add({ type:"sphere", size:[0.1], pos:[ 2, 3, 0], move:false });

// 滑轮（可上下移动）
let pulley = world.add({ type:"cylinder", size:[0.3, 0.1], pos:[0, 2, 0], rot:[90,0,0], move:true });

// 限制滑轮只能上下移动（PrismaticJoint）
world.add({
    type: "jointPrismatic",
    body1: pulley,
    body2: null,
    axis1: [0,1,0],
    axis2: [0,1,0],
    lowerLimit: -1,
    upperLimit: 1
});

// 绘制滑轮Mesh
let pulleyMesh = BABYLON.MeshBuilder.CreateCylinder("pulley", { height: 0.1, diameter: 0.6 }, scene);
pulleyMesh.rotation.z = Math.PI/2;
pulleyMesh.material = new BABYLON.StandardMaterial("pmat", scene);
pulleyMesh.material.diffuseColor = new BABYLON.Color3(1,0.8,0.4);

// 创建绳子
function createRope(startBody, endBody, segs) {
    let bodies = [];
    let prev = startBody;
    let segLength = 0.2;
    for (let i = 0; i < segs; i++) {
        let p = prev.getPosition();
        let body = world.add({ type:"sphere", size:[0.05], pos:[p.x, p.y - segLength, p.z], move:true });
        world.add({ type:"jointDistance", body1: prev, body2: body, distance: segLength });
        bodies.push(body);
        prev = body;
    }
    world.add({ type:"jointDistance", body1: prev, body2: endBody, distance: segLength });
    return bodies;
}

let rope1Bodies = createRope(anchorA, pulley, 10);
let rope2Bodies = createRope(pulley, anchorB, 10);

// Tube 绳子
let rope1Mesh = BABYLON.MeshBuilder.CreateTube("rope1", { path: [], radius: 0.05, updatable: true }, scene);
rope1Mesh.material = new BABYLON.StandardMaterial("r1mat", scene);
rope1Mesh.material.diffuseColor = new BABYLON.Color3(0.3,0.3,0.3);

let rope2Mesh = BABYLON.MeshBuilder.CreateTube("rope2", { path: [], radius: 0.05, updatable: true }, scene);
rope2Mesh.material = new BABYLON.StandardMaterial("r2mat", scene);
rope2Mesh.material.diffuseColor = new BABYLON.Color3(0.3,0.3,0.3);

// 动画循环
scene.onBeforeRenderObservable.add(() => {
    world.step();

    // 同步滑轮Mesh
    let pp = pulley.getPosition();
    pulleyMesh.position.set(pp.x, pp.y, pp.z);

    // 绳子路径
    let pAnchorA = anchorA.getPosition();
    let pAnchorB = anchorB.getPosition();

    let path1 = [new BABYLON.Vector3(pAnchorA.x, pAnchorA.y, pAnchorA.z), new BABYLON.Vector3(pp.x, pp.y, pp.z)];
    let path2 = [new BABYLON.Vector3(pp.x, pp.y, pp.z), new BABYLON.Vector3(pAnchorB.x, pAnchorB.y, pAnchorB.z)];

    BABYLON.MeshBuilder.CreateTube("rope1", { path: path1, instance: rope1Mesh });
    BABYLON.MeshBuilder.CreateTube("rope2", { path: path2, instance: rope2Mesh });
});

// 控制滑轮上下移动
window.addEventListener("keydown", e => {
    let p = pulley.getLinearVelocity();
    if (e.key === "w") pulley.setLinearVelocity(new OIMO.Vec3(0, 1, 0));
    if (e.key === "s") pulley.setLinearVelocity(new OIMO.Vec3(0,-1, 0));
});

engine.runRenderLoop(() => scene.render());
</script>
</body>
</html>
